/**
 * 
 */
package any.desktop.gwt.client;

import java.util.HashMap;
import java.util.Map;

import any.desktop.gwt.client.ui.SearchBox;
import any.desktop.gwt.client.ui.SearchView;
import any.gwt.client.http.AsynClientEvent;
import any.gwt.client.http.AsynClientListener;
import any.gwt.client.util.DispacherContainer;
import any.gwt.client.util.DispatchEvent;
import any.gwt.client.util.DispatcherListener;
import any.gwt.client.util.GWTUtil;
import any.tag.gwt.client.TagClient;
import any.tag.gwt.client.ui.TagListView;

import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.http.client.URL;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.HistoryListener;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.WindowResizeListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.SimplePanel;

/**
 * TODO: doc me
 * 
 * @author keke<keke@codehaus.org>
 * @revision $Revision: 90 $
 * @version
 */
public class DesktopApplication extends Composite implements
        WindowResizeListener, HistoryListener, AsynClientListener,
        DispatcherListener {

    private final FlowPanel    header;
    private final SimplePanel  mainOut;
    private final SearchClient searchClient;
    private final TagClient    tagClient;

    public DesktopApplication() {
        final FlowPanel outer = new FlowPanel();
        DispacherContainer.getGlobalDispatcher().addDispatcherListener(this);
        header = new FlowPanel();
        tagClient = new TagClient();
        searchClient = new SearchClient();
        tagClient.addClientListener(this);
        searchClient.addClientListener(this);
        header.add(new SearchBox());
        outer.add(header);
        mainOut = new SimplePanel();
        mainOut.setStyleName("main-out");
        outer.add(mainOut);
        initWidget(outer);
        setStyleName("appMain");
        Window.addWindowResizeListener(this);
        History.addHistoryListener(this);
    }

    public void fireDispatchEvent(final DispatchEvent event) {
        if (event.isConsumed()) {
            return;
        }
        if (event.getName().equals("doSearch")) {
            mainOut.setWidget(new SearchView());
            searchClient.search((String) event.getContent(), 0);
        } else if (event.getName().equals("openItem")) {
            searchClient.openItem((String) event.getContent());
        } else if (event.getName().equals("loadingTagBar")) {
            final String uri = (String) event.getContent();
            tagClient.getTagsOfURI(uri, new AsynClientListener() {
                public void fireEvent(final AsynClientEvent event) {
                    if (!event.isFailed()) {
                        final DispatchEvent de = new DispatchEvent(this,
                                new Object[] {
                                        uri,
                                        JSONParser.parse(
                                                event.getResponse().getText())
                                                .isArray() }, "tagItemsLoaded");
                        DispacherContainer.getGlobalDispatcher().dispatch(de);
                    }

                }
            });
        } else if (event.getName().equals("saveTags")) {
            final Object[] content = (Object[]) event.getContent();
            final String tags = (String) content[0];
            final String uri = (String) content[1];
            tagClient.tag(tags, uri, new AsynClientListener() {

                public void fireEvent(final AsynClientEvent event) {
                    if (!event.isFailed()) {
                        final DispatchEvent de = new DispatchEvent(this,
                                new Object[] {
                                        uri,
                                        JSONParser.parse(
                                                event.getResponse().getText())
                                                .isArray() }, "tagsSaved");
                        DispacherContainer.getGlobalDispatcher().dispatch(de);
                    }
                }
            });

        } else if (event.getName().equals("openTag")) {
            tagClient.getItemsByTag((String) event.getContent(), null);
        }
    }

    public void fireEvent(final AsynClientEvent event) {
        if (event.getName().equals("search")) {
            if (Log.isDebugEnabled()) {
                Log.debug("Get Search Results");
            }
            DispacherContainer.getGlobalDispatcher().dispatch(
                    new DispatchEvent(this, JSONParser.parse(
                            event.getResponse().getText()).isObject(),
                            "searchResult"));
        } else if (event.getName().equals("tags")) {
            if (!(mainOut.getWidget() instanceof TagListView)) {
                mainOut.clear();
                final TagListView view = new TagListView(tagClient);
                mainOut.setWidget(view);
                view.fireEvent(event);
            }
        }
    }

    public void onHistoryChanged(final String historyToken) {
        final String path = URL.decode(historyToken);
        if (Log.isDebugEnabled()) {
            Log.debug("History Token is " + path);
        }
        if (path.startsWith("/search")) {
            mainOut.setWidget(new SearchView());
            final String[] param = path.substring(path.indexOf("?") + 1).split(
                    "&");
            final Map paramMap = new HashMap();
            for (int i = 0; i < param.length; i++) {
                final String[] parts = param[i].split("=");
                paramMap.put(parts[0], parts[1]);
            }
            if (Log.isDebugEnabled()) {
                Log.debug("Params : " + paramMap);
            }
            searchClient.search((String) paramMap.get("q"), Integer
                    .parseInt((String) paramMap.get("s")));
        } else if (path.startsWith("/tag")) {
            mainOut.setWidget(new TagListView(tagClient));
            final String tagName = path.substring(5);
            tagClient.getItemsByTag(tagName.trim(), null);
        }

    }

    public void onWindowResized(final int width, final int height) {
        if (Log.isDebugEnabled()) {
            Log.debug("Window height=" + height);
        }
        mainOut.setHeight(height - header.getOffsetHeight() - 16 + "px");
    }

    protected void onLoad() {
        onWindowResized(Window.getClientWidth(), Window.getClientHeight());
        final String hash = URL.decode(GWTUtil.getHash());
        if (hash != null && hash.trim().length() != 0) {
            History.onHistoryChanged(hash.substring(1));
        }
    }

}
